package com.oa.erp.pur.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.err.BizException;
import com.mdp.core.service.BaseService;
import com.mdp.core.utils.BaseUtils;
import com.oa.erp.ass.entity.AssetDetail;
import com.oa.erp.ass.service.AssetCardService;
import com.oa.erp.ass.service.AssetDetailService;
import com.oa.erp.pur.entity.OrderDetail;
import com.oa.erp.pur.entity.StockIn;
import com.oa.erp.pur.entity.StockInDetail;
import com.oa.erp.pur.mapper.StockInDetailMapper;
import com.oa.erp.pur.vo.StockInAddVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月8日
 */
@Service
public class StockInDetailService extends BaseService<StockInDetailMapper, StockInDetail> {
    static Logger logger = LoggerFactory.getLogger(StockInDetailService.class);

    /**
     * 自定义查询，支持多表关联
     *
     * @param page 分页条件
     * @param ew   一定要，并且必须加@Param("ew")注解
     * @param ext  如果xml中需要根据某些值进行特殊处理，可以通过这个进行传递，非必须，注解也可以不加
     * @return
     */
    public List<Map<String, Object>> selectListMapByWhere(IPage page, QueryWrapper ew, Map<String, Object> ext) {
        return baseMapper.selectListMapByWhere(page, ew, ext);
    }
 

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private AssetDetailService assetDetailService;

    @Lazy
    @Autowired
    private StockInService stockInService;

    @Autowired
    private AssetCardService assetCardService;


    @Autowired
    private OrderService orderService;


    @Transactional
    public void insertStockIn(StockInAddVo stockInAddVo) {
        StockIn stockIn = stockInAddVo.getStockIn();
        List<StockInDetail> stockInDetails = stockInAddVo.getStockInDetails();

        //1.添加入库单主表
		this.saveBatch(stockInDetails);


        //2.添加入库单明细表
        this.batchInsert(stockInDetails);


        List<StockInDetail> orderDetails = stockInDetails.stream().filter(i -> StringUtils.hasText(i.getPurOrderId())).collect(Collectors.toList());
        List<String> orderIds = orderDetails.stream().map(i -> i.getPurOrderId()).collect(Collectors.toList());
        if (orderIds != null && orderIds.size() > 0) {
            this.orderService.updateReachNumByOrderId(orderIds);
        }

    }

    /**
     * 修改资产入库单
     *
     * @param stockInAddVo
     */
    @Transactional
    public void updateStockIn(StockInAddVo stockInAddVo) {
        StockIn stockIn = stockInAddVo.getStockIn();
        //1.添加入库单主表
        this.updateBatchById(stockInAddVo.getStockInDetails());

        List<StockInDetail> details = stockInAddVo.getStockInDetails();
        StockInDetail stockInDetailQuery = new StockInDetail();
        stockInDetailQuery.setReceiptNo(stockInAddVo.getStockIn().getId());
        List<StockInDetail> stockInDetailsDb = this.selectListByWhere(stockInDetailQuery);
        List<StockInDetail> detailsInsert = new ArrayList<>();
        List<StockInDetail> detailsUpdate = new ArrayList<>();
        List<StockInDetail> detailsDel = new ArrayList<>();
        for (StockInDetail stockInDetail : stockInDetailsDb) {
            if (!details.stream().filter(i -> i.getAssetSn().equals(stockInDetail.getAssetSn())).findFirst().isPresent()) {
                detailsDel.add(stockInDetail);
            }
        }

        for (StockInDetail detail : details) {
            if (stockInDetailsDb.stream().filter(i -> i.getAssetSn().equals(detail.getAssetSn())).findFirst().isPresent()) {
                detailsUpdate.add(detail);
            } else {
                detail.setReceiptNo(stockIn.getId());
                detailsInsert.add(detail);
            }
        }
        //2.添加入库单明细表
        if (detailsInsert.size() > 0) {
            this.batchInsert(detailsInsert);
        }
        if (detailsUpdate.size() > 0) {
            this.batchUpdate(detailsUpdate);
        }

        if (detailsDel.size() > 0) {
            this.batchDelete(detailsDel);
        }

        List<StockInDetail> orderDetails = details.stream().filter(i -> StringUtils.hasText(i.getPurOrderId())).collect(Collectors.toList());
        List<String> orderIds = orderDetails.stream().map(i -> i.getPurOrderId()).collect(Collectors.toList());
        if (orderIds != null && orderIds.size() > 0) {
            this.orderService.updateReachNumByOrderId(orderIds);
        }

    }

    /**
     * 通过入库单id查询对应的入库单明细和采购单明细
     *
     * @param id
     * @return
     */
    public Map<String, Object> listStorkInDetail(String id) {

        Map<String, Object> result = new HashMap<>();
        //1.通过入库单id查询入库单明细
        Map<String, Object> params = new HashMap<>();
        params.put("receiptNo", id);
        List<Map<String, Object>> storkInDetail = baseMapper.selectDetailByReceiptNo(params);
        //2.通过明细单中的入库单id查询相对应的采购单信息
        Set idSet = new HashSet();
        for (Map<String, Object> map : storkInDetail) {
            idSet.add(map.get("purOrderId"));
        }
        List<String> idList = new ArrayList();
        idList.addAll(idSet);
        if (idList.size() > 0) {
            List<OrderDetail> orderDetails = orderDetailService.selectDetailByPurOrderIds(idList);

            result.put("caiGouData", orderDetails);
        } else {
            result.put("caiGouData", new ArrayList<>());
        }

        result.put("ruKuData", storkInDetail);
        return result;
    }


    /**
     * 删除入库单
     *
     * @param stockIn
     */
    public void delStockIn(StockIn stockIn) {
        //1.删除主表
//        this.deleteByPk(stockIn);
        //2.删除关联表
        Map<String, Object> param = new HashMap<>();
        param.put("receiptNo", stockIn.getId());
        this.deleteByWhere(BaseUtils.fromMap(param, StockInDetail.class));
    }

    /**
     * 验证资产编码是否存在
     */
    public long assetSnIsExit(List<String> queryParams) {
        List<AssetDetail> list = assetCardService.selectAssetSnIsExit(queryParams);
        return list.size();
    }

    /**
     * 流程审批过程中回调该接口，更新业务数据
     * 如果发起流程时上送了restUrl，则无论流程中是否配置了监听器都会在流程发生以下事件时推送数据过来
     * eventName: PROCESS_STARTED 流程启动完成 全局
     * PROCESS_COMPLETED 流程正常结束 全局
     * PROCESS_CANCELLED 流程删除 全局
     * create 人工任务启动
     * complete 人工任务完成
     * assignment 人工任务分配给了具体的人
     * delete 人工任务被删除
     * TASK_COMPLETED_FORM_DATA_UPDATE 人工任务提交完成后，智能表单数据更新
     * <p>
     * 其中 create/complete/assignment/delete事件是需要在模型中人工节点上配置了委托代理表达式 ${taskBizCallListener}才会推送过来。
     * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
     *
     * @param flowVars {flowBranchId,agree,procInstId,startUserid,assignee,actId,taskName,mainTitle,branchId,bizKey,commentMsg,eventName,modelKey} 等
     * @return 如果tips.isOk==false，将影响流程提交
     **/
    @Transactional
    public void processApprova(IPage page, QueryWrapper ew, Map<String, Object> flowVars) {
        String eventName = (String) flowVars.get("eventName");
        String agree = (String) flowVars.get("agree");
        String branchId = (String) flowVars.get("branchId");
        String receiptNo = (String) flowVars.get("receiptNo");//入库单号
        String bizKey = (String) flowVars.get("bizKey");
        if ("erp_stock_in_approva".equals(bizKey)) {
        } else {
            throw new BizException("不支持的业务,请上送业务编码【bizKey】参数");
        }

        if ("complete".equals(eventName)) {
            if ("1".equals(agree)) {
                this.updateFlowStateByProcInst(null, flowVars);
            } else {
                this.updateFlowStateByProcInst(null, flowVars);
            }
        } else {
            //废弃：监听资产管理员，create->待入库
            // PROCESS_COMPLETED->待入库
            if ("TASK_CREATED".equals(eventName)) {
                //办公用品管理员节点ID已写死为om_appliance_keeper
                /*if ("asset_keeper".equals(flowVars.get("actId"))) {
                    //流程表和采购单表更新为2,表示待入库
                    this.updateFlowStateByProcInst("2",flowVars);
                }*/
            } else {
                if ("PROCESS_STARTED".equals(eventName)) {
                    Map<String, Object> bizQuery = new HashMap<>();
                    bizQuery.put("id", receiptNo);
                    if (StringUtils.isEmpty(receiptNo)) {
                        throw new BizException("请上送入库单编号-receiptNo");
                    }
                    if (StringUtils.isEmpty(branchId)) {
                        throw new BizException("请上送branchId");
                    }
                    List<Map<String, Object>> bizList = this.selectListMapByWhere(page, ew, bizQuery);
                    if (bizList == null || bizList.size() == 0) {
                        throw new BizException("没有找到对应入库单,入库单为【" + receiptNo + "】");
                    } else {
                        Map<String, Object> bizObject = bizList.get(0);
                        if ("1".equals(bizObject.get("bizFlowState"))) {
                            throw new BizException("该入库单正在审批中，不能再发起审批");
                        }
                    }
                    this.updateFlowStateByProcInst("1", flowVars);
                } else if ("PROCESS_COMPLETED".equals(eventName)) {
                    //流程表、订单表更新
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    if ("1".equals(agree)) {
                        StockIn stockIn = stockInService.getById(receiptNo);

                        StockInDetail stockInDetail = new StockInDetail();
                        stockInDetail.setReceiptNo(receiptNo);
                        List<StockInDetail> stockInDetails = this.selectListByWhere(stockInDetail);
                        this.assetDetailService.insertAssetDetail(stockIn, stockInDetails);
                        List<StockInDetail> orderDetails = stockInDetails.stream().filter(i -> StringUtils.hasText(i.getPurOrderId())).collect(Collectors.toList());
                        List<String> orderIds = orderDetails.stream().map(i -> i.getPurOrderId()).collect(Collectors.toList());
                        flowVars.put("stockStatus", "1");
                        this.updateFlowStateByProcInst("2", flowVars);
                        if (orderIds != null && orderIds.size() > 0) {
                            this.orderService.updateReachNumByOrderId(orderIds);
                        }
                    } else {
                        //5为未通过状态
                        this.updateFlowStateByProcInst("3", flowVars);
                    }
                } else if ("PROCESS_CANCELLED".equals(eventName)) {
                    //4为流程取消状态
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    this.updateFlowStateByProcInst("4", flowVars);
                }
            }
        }
    }

    //update等级表状态、流程表信息
    public void updateFlowStateByProcInst(String flowState, Map<String, Object> flowVars) {
        flowVars.put("bizFlowState", flowState);
        flowVars.put("id", flowVars.get("receiptNo"));
        if ("1".equals(flowState)) {
            flowVars.put("bizProcInstId", flowVars.get("procInstId"));
        }
//        this.updateSomeFieldByPk(flowVars);
        this.updateStockIn(BaseUtils.fromMap(flowVars, StockInAddVo.class));
    }

    public List<Map<String, Object>> selectDetailByReceiptNo(Map<String, Object> params) {
        return baseMapper.selectDetailByReceiptNo(params);
    }
}

